
import { _decorator, Component, Node, Prefab, instantiate, Vec3,sys, Label } from 'cc';
import { PlayerController } from './PlayerController';
const { ccclass, property } = _decorator;

/**
 * Predefined variables
 * Name = GameManager
 * DateTime = Sun Nov 28 2021 19:17:47 GMT+0800 (中国标准时间)
 * Author = 悟柒非梦
 * FileBasename = GameManager.ts
 * FileBasenameNoExtension = GameManager
 * URL = db://assets/Scripts/GameManager.ts
 * ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
 *
 */

// 赛道方块类型
enum BlockType {
    BT_NONE,// 坑0
    BT_STONE,// 石头1
}
enum GameState {
    GS_INIT,
    GS_PLAYING,
    GS_END
}

@ccclass('GameManager')
export class GameManager extends Component {
    // [1]
    // dummy = '';
    private _rodeStep = 0;

    // 赛道的长度
    private roadLength = 40;
    // 赛道集合
    private _road: BlockType[] = [];


    // 引入赛道方块的预制体
    @property({ type: Prefab })
    public cubePrefb: Prefab | null = null;

    
    // 引入角色控制脚本
    @property({ type: PlayerController })
    public playerCtrl: PlayerController | null = null;

    // 引入菜单控制
    @property({ type: Node })
    public startMenu: Node | null = null;

    // 引入菜单控制
    @property({ type: Label })
    public stepLabel: Label | null = null;


    start() {
        // [3]
        this._rodeStep = this.roadLength;
        this.curState = GameState.GS_INIT;
        this.playerCtrl?.node.on('JumpEnd',this.onPlayJumpEnd,this)
    
    }

    init() {
        // 激活主界面
        if (this.startMenu) {
            this.startMenu.active = true
        }
        // 生成赛道
        this.buildRoad(true);
        if (this.playerCtrl) {
            this.playerCtrl.setInputActive(false);
            this.playerCtrl.node.setPosition(Vec3.ZERO)
            this.playerCtrl.reset();
        }
    }

    set curState(value: GameState) {
        switch (value) {
            case GameState.GS_INIT:
                this.init();
                break
            case GameState.GS_PLAYING:
                if (this.startMenu) {
                    this.startMenu.active = false;
                    this.stepLabel.string = '0';
                }
                setTimeout(() => {
                    if (this.playerCtrl) {
                        this.playerCtrl.setInputActive(true)
                    }
                }, 0.1);
            case GameState.GS_INIT:
                break
        }
    }

    onStartButtonClicked() {
        this.curState = GameState.GS_PLAYING
    }

    /**
     * 构建赛道
     * @param isReset 是否重新构建
     */
    buildRoad(isReset:boolean) {
        // 重新构建 移除所有赛道节点和数据
        if(isReset){
            this.node.removeAllChildren();
            this._road = [];
        }
        // 先push一个石头块，防止一开始就入坑
        this._road.push(BlockType.BT_STONE);

        // 已存在赛道数据长度
        let tempIndex = this._road.length;
        // 当前赛道石头块数量
        const _curNodeChildLength = this.node.children.length;

        // 本次构建赛道长度，如果重新构建：取预设的长度，增量构建：已存在长度+预设的长度
        const _curRoadLength = isReset?this.roadLength:tempIndex+this._rodeStep;

        // 1、 生成本次需构建的赛道数据集合（包括石头和坑）
        for (let i = tempIndex; i < _curRoadLength; i++) {
            if (this._road[i - 1] === BlockType.BT_NONE) {
                this._road.push(BlockType.BT_STONE)
            } else {
                this._road.push(Math.floor(Math.random() * 2))
            }
        }
        // 2、遍历赛道集合中不同类型的模块，如果是石头类型，增加到赛道节点中
        for (let i = tempIndex-1; i < this._road.length; i++) {
            let block: Node = this.buildBlockByType(this._road[i]);
            if (block) {
                this.node.addChild(block);
                block.setPosition(i, -1.5, 0)
            }
        }
        // 3、如果是增量构建赛道，则动态地删除已经不需要的赛道节点
        if(!isReset){
            let removeLength = Math.floor((_curNodeChildLength-6)/2);
            console.log('现在长度'+this.node.children.length+',移除'+removeLength)
            for (let i = 0; i < removeLength; i++) {
                this.node.removeChild(this.node.children[i])

            }
            // 需要移除的数量=上次已存在的数量/2
        }
        console.log('节点',this.node.children)
        console.log('赛道',this._road)
    }

    /**
     * 根据赛道格子类型生成赛道
     * @param type 类型
     * @returns 
     */
    buildBlockByType(type: BlockType) {
        if (!this.cubePrefb) return null;

        let block: Node | null = null;

        switch (type) {
            case BlockType.BT_STONE:
                // 克隆预制立方体
                block = instantiate(this.cubePrefb);
                break;

        }
        return block;
    }

    checkResule(moveIndex:number){
        if(moveIndex<this._road.length){
            if(this._road[moveIndex] === BlockType.BT_NONE){
                console.log('坑')
                this.curState = GameState.GS_INIT
            }
            if(this._road.length-moveIndex<10){// 剩下的赛道格子不足10格时，增加新的赛道
                this.buildRoad(false)
            }
            if (this.stepLabel) {
                // 因为在最后一步可能出现步伐大的跳跃，但是此时无论跳跃是步伐大还是步伐小都不应该多增加分数
                this.stepLabel.string = ''+ moveIndex;
            }
        }else{
            console.log('超过赛道')
            this.curState = GameState.GS_INIT
        }
    }

    onPlayJumpEnd(moveIndex:number){
        this.checkResule(moveIndex)
    }

    // update (deltaTime: number) {
    //     // [4]
    // }
}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.3/manual/zh/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.3/manual/zh/scripting/ccclass.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.3/manual/zh/scripting/life-cycle-callbacks.html
 */
